from socket import *
import struct

s = socket(AF_INET, SOCK_DGRAM)

host_server = ('', 69)

s.bind(host_server)

def download(filename, client_ip, client_port):
    # 创建新的socket, 负责发送文件内容的数据包到客户端
    new_socket = socket(AF_INET, SOCK_DGRAM)
    num = 1

    # 定义客户端退出的标签
    flag = True

    try:
        f = open(filename,'rb')
    except:
        # 创建错误数据包
        error_package = struct.pack('!HH5sb', 5, 5, 'error'.encode('utf-8'), 0)
        new_socket.sendto(error_package,(client_ip,client_port))
        # exit() # 当前线程结束，当前客户端退出服务器
        flag = False
    # 如果文件存在，每次读取512字节发送客户端
    while flag:
        # 从文件内容中读取
        read_data = f.read(512) # 字节数据
        data_package = struct.pack('!HH',3,num) + read_data
        new_socket.sendto(data_package,(client_ip, client_port))
        if len(read_data)<512:
            print(f'客户端 {client_ip}，文件下载完成')
            flag = False
        recv_ack = new_socket.recvfrom(1024)
        operator_code, ack_num = struct.unpack('!HH',recv_ack[0])
        print(f'客户端 {client_ip}的确认信息是 {ack_num}')
        num += 1
        # 保护性代码
        if int(operator_code) != 4 or int(ack_num) < 1:
            flag = False
    f.close()
    new_socket.close()


def server():
    while True:
        # 服务器等待客户端发送数据，然后等着接受
        recv_data, (client_ip, client_port) = s.recvfrom(1024)
        print(recv_data, client_ip, client_port)
        # 判断数据包是否是客户端请求的数据包
        if (0, b'octet', 0) == struct.unpack('!b5sb', recv_data[-7:]):
            operator_code = struct.unpack('!H',recv_data[:2])
            file_name = recv_data[2:-7].decode('utf-8')
            print(operator_code, file_name)
            if operator_code[0] == 1: # 如果为1 是下载的请求数据包
                download(file_name, client_ip, client_port)




if __name__ == "__main__":
    server()
